<template>
    <div class="w100 h100 p-r">
        <div :id="id"></div>
        <div
            :id="'yan-pan-modal-' + item.areaCode"
            v-for="item in markerList"
            :key="item.name"
            class="yan-pan-modal v-center p-a z3 p5 pb15 pt15"
            style="display: none !important"
        >
            <div class="ell f12">{{ item.timeStr || '2021.8-2024.8' }}</div>
            <div class="fam ell h-center">
                <div class="mr5 dot" :style="`background-color:${colors[item.state]}`"></div>
                <div>
                    {{ item.name }}
                </div>
            </div>
        </div>
        <svg class="dn" width="24px" height="32px" viewBox="0 0 24 32">
            <defs>
                <filter id="blurFilter2" y="-10" height="40" x="-10" width="150">
                    <feOffset in="SourceGraphic" dx="0" dy="10" result="offset0" />
                    <feGaussianBlur in="offset0" stdDeviation="15" result="blur2" />
                    <feOffset in="SourceGraphic" dx="0" dy="1" result="offset1" />
                    <feOffset in="SourceGraphic" dx="0" dy="2" result="offset2" />
                    <feOffset in="SourceGraphic" dx="0" dy="3" result="offset3" />
                    <feOffset in="SourceGraphic" dx="0" dy="4" result="offset4" />
                    <feOffset in="SourceGraphic" dx="0" dy="5" result="offset5" />
                    <feOffset in="SourceGraphic" dx="0" dy="6" result="offset6" />
                    <feOffset in="SourceGraphic" dx="0" dy="7" result="offset7" />
                    <feOffset in="SourceGraphic" dx="0" dy="8" result="offset8" />
                    <feOffset in="SourceGraphic" dx="0" dy="9" result="offset9" />
                    <feOffset in="SourceGraphic" dx="0" dy="10" result="offset10" />

                    <feMerge>
                        <!--                        <feMergeNode in="offset10" />-->
                        <!--                        <feMergeNode in="offset9" />-->
                        <!--                        <feMergeNode in="offset8" />-->
                        <!--                        <feMergeNode in="offset7" />-->
                        <!--                        <feMergeNode in="offset6" />-->
                        <!--                        <feMergeNode in="offset5" />-->
                        <!--                        <feMergeNode in="offset4" />-->
                        <!--                        <feMergeNode in="offset3" />-->
                        <!--                        <feMergeNode in="offset2" />-->
                        <!--                        <feMergeNode in="offset1" />-->
                        <!--                        <feMergeNode in="blur2" />-->
                        <feMergeNode in="SourceGraphic" />
                    </feMerge>
                </filter>

                <g id="yan-pan-icon">
                    <path
                        d="M22.1628914,16.5 L15.4960882,28.8812059 C15.5438791,29.6080861 15.1498558,30.2552489 14.5284271,30.7213203 C13.8813462,31.206631 12.9857964,31.5 12,31.5 C11.0142036,31.5 10.1186538,31.206631 9.47157288,30.7213203 C8.85014424,30.2552489 8.45612085,29.6080861 8.50391175,28.8812059 L8.50391175,28.8812059 L1.83710858,16.5 L22.1628914,16.5 Z"
                        fill="#FF4746"
                        stroke="currentColor"
                        stroke-width="1"
                    ></path>
                    <circle stroke="currentColor" stroke-width="1" fill="#D32B2A" cx="12" cy="12" r="11.5"></circle>
                </g>
            </defs>
        </svg>
    </div>
</template>
<script>
import Chart from '../../chart.js'
import * as d3 from 'd3'
import * as topojson from 'topojson'
import axios from 'axios'

export default {
    props: {
        id: {
            required: true,
        },
        width: {},
        height: {},
        markerList: [],
        adcode: {},
    },
    data() {
        return {
            scale: 4000,
            provinceScale: 3800,
            level: 'province',
            parentAdcode: null,
            chart: null,
            projection: null,
            currentMarker: {},
            colors: ['white', '#00B928', '#FF2D2E', 'white'],
        }
    },
    mounted() {},
    watch: {
        markerList: {
            handler() {
                setTimeout(() => {
                    this.closeModal()
                    this.chartRenderCenter()
                }, 500)
            },
            immediate: true,
        },
        adcode: {
            async handler(val) {
                if (val) {
                    if (val == 510000) {
                        this.level = 'province'
                    } else {
                        this.level = 'city'
                    }
                    this.closeModal()
                    this.chart = null
                    this.iconArr = null
                    await this.getGeoDataFn()
                }
            },
            immediate: true,
        },
    },
    methods: {
        getGeoData(code) {
            let url = `/sc/${code}_geojson.json`
            if (code % 100 === 0) {
                url = `/sc/${code}_geojson_full.json`
            }
            return axios({
                method: 'get',
                url,
            })
        },
        geoToTopo(geojson) {
            let topo_data
            try {
                // 将 GeoJSON 数据转成 TopoJSON 格式
                topo_data = topojson.topology(
                    {
                        geo: geojson,
                    },
                    1e6,
                )
            } catch (e) {
                return console.error(e)
            }
            return topo_data
        },
        chartRenderCenter() {
            let me = this
            this.$nextTick(() => {
                me.markerList.forEach(n => {
                    let position = me.projection(me.scale)([n.longitude, n.latitude])
                    console.log(d3.select('#yan-pan-modal-' + n.areaCode))
                    d3.select('#yan-pan-modal-' + n.areaCode).attr(
                        'style',
                        `left:${position[0] + 90}px;top:${position[1] - 20}px;display:block`,
                    )
                })
            })
        },

        closeModal() {
            d3.select('.yan-pan-modal').attr('style', `display:none`)
        },
        goBack() {
            if (this.level === 'district') {
                this.adcode = this.parentAdcode
                this.level = 'city'
            } else if (this.level === 'city') {
                this.adcode = 510000
                this.level = 'province'
            }
            this.getGeoDataFn()
        },
        async getGeoDataFn() {
            this.scale = this.level === 'province' ? this.provinceScale : this.level == 'city' ? 25000 : 30000
            if ([513200, 513400].includes(this.adcode)) {
                this.scale = 10000
            }
            if (this.adcode === 513300) {
                this.scale = 6000
            }
            if ([510700, 511700, 511800].includes(this.adcode)) {
                this.scale = 18000
            }
            if ([510900, 511000, 511600, 512000].includes(this.adcode)) {
                this.scale = 35000
            }
            try {
                let res = await this.getGeoData(this.adcode)
                if (res.status === 200) {
                    this.initMap(res.data)
                }
            } catch (e) {
                console.log(e)
            }
        },
        initMap(geoData) {
            const me = this
            let data = this.geoToTopo(geoData)
            const box = d3.select('#' + this.id)
            box.node().innerHTML = ''
            const chart = new Chart()
            this.chart = chart
            chart.setId(this.id)

            box.node().style.width = this.width + 'px'
            box.node().style.height = this.height + 'px'
            const config = {
                margins: { top: 20, left: 80, bottom: 0, right: 80 },
                textColor: 'black',
                title: '中国地图',
                hoverColor: 'white',
            }

            chart.box(box)
            chart.margins(config.margins)

            chart.setId(this.id)
            chart.width(this.width)
            chart.height(this.height)

            /* ----------------------------尺度转换------------------------  */
            const boxLatLng = topojson.bbox(data)
            const center = [(boxLatLng[0] + boxLatLng[2]) / 2, (boxLatLng[1] + boxLatLng[3]) / 2]

            // 获取边界值对应的投影中的xy

            function getXY(arr) {
                let sx, sy
                d3.geoProjection(function (x, y) {
                    sx = x
                    sy = y
                    return [x, y]
                })(arr)
                return [sx, sy]
            }

            //获取经伟度在标投影计算中对应的x,y，以便用于投影转换中进行x轴坐标的的拉升与缩放
            let centerGeo = getXY(center)
            let topGeo = getXY([boxLatLng[0], boxLatLng[1]])
            let bottomGeo = getXY([boxLatLng[2], boxLatLng[3]])

            // 定义从地图从顶部到底部的缩放比例尺
            let geoScale = d3.scaleLinear().domain([topGeo[1], bottomGeo[1]]).range([1.2, 0.8])

            let geoProjection = d3.geoProjection(function (x, y) {
                let yNew = Math.log(Math.tan(Math.PI / 4 + y / 2)) * 0.67
                let xNew
                // 变换地图x坐标，顶部绽放，底部拉升
                if (x > centerGeo[0]) {
                    xNew = centerGeo[0] + (x - centerGeo[0]) * geoScale(y)
                } else {
                    xNew = centerGeo[0] - (centerGeo[0] - x) * geoScale(y)
                }
                return [xNew, yNew]
            })

            function projection(scale) {
                return geoProjection
                    .rotate([0, 0, 0])
                    .angle(0)
                    .center(center)
                    .scale(scale)
                    .translate([chart.getBodyWidth() / 2, chart.getBodyHeight() / 2])
            }
            this.projection = projection
            /* ----------------------------准备数据------------------------  */

            // 获取最外层轮廓路径的 GeoJSON
            const geo_border = topojson.merge(data, data.objects.geo.geometries)

            // 获取不包含最外层轮廓的其余边界路径的 GeoJSON，得到
            // 的是一个单一的路径，不存在边界重叠问题
            const geo_interiors = topojson.mesh(data, data.objects.geo, (a, b) => a !== b)

            const handleData = topojson.feature(data, data.objects.geo).features

            /* ----------------------------定义过滤器 ------------------------  */

            /* ----------------------------渲染地图轮廓------------------------  */

            let mapTop

            //第一层（最底层），各区域面积，这一层仅仅渲染区域颜色，不包含边框
            chart.mapArea = function () {
                const path = d3.geoPath().projection(projection(me.scale))

                let mapArea = mapTop.append('g').selectAll('path').data(geoData.features)

                mapArea
                    .enter()
                    .append('path')
                    .attr('class', d => 'provinces ' + d.properties.name)
                    .merge(mapArea)
                    .attr('d', path)
                    // .attr('fill', (d, i) => chart._colors(i % 10))
                    .attr('stroke', 'none')
                    .attr('fill', '#0062FF')
                    .attr('opacity', () => {
                        let opacity
                        let i = Math.floor(Math.random() * 4)
                        switch (i) {
                            case 0:
                                opacity = '0.2'
                                break
                            case 1:
                                opacity = '0.4'
                                break
                            case 2:
                                opacity = '0.6'
                                break
                            case 3:
                                opacity = '0.8'
                                break
                            default:
                                opacity = '0.8'
                                break
                        }
                        return opacity
                    })
                mapArea.exit().remove()
            }
            // 第二层，内部边界线路径
            chart.mapInterior = function () {
                const path = d3.geoPath().projection(projection(me.scale))

                let mapInterior = mapTop.append('g').append('path').datum(geo_interiors)

                mapInterior.attr('d', path).attr('stroke', '#0062FF').attr('stroke-width', 0.5).attr('fill', 'none')
            }
            // 绘制第三层最外圈轮廓线
            chart.mapOutline = function () {
                const path = d3.geoPath().projection(projection(me.scale + 5))

                let mapOutline = mapTop.append('g').append('path').datum(geo_border)

                mapOutline
                    .attr('class', 'layer-outline ')
                    .merge(mapOutline)
                    .attr('d', path)
                    .attr('stroke', '#00B1FF')
                    .attr('stroke-width', '1')
                    // .attr('fill', (d, i) => chart._colors(i % 10))
                    .attr('fill', 'none')
            }
            // 绘制第四层交互层
            chart.mapOverlays = function () {
                const path = d3.geoPath().projection(projection(me.scale))

                let mapOverlays = mapTop.append('g').selectAll('path').data(handleData)

                mapOverlays
                    .enter()
                    .append('path')
                    .attr('class', d => 'mapOverlays-' + d.properties.name)
                    .classed('pointer', true)
                    .classed('mapOverlays', true)
                    .merge(mapOverlays)
                    .attr('d', path)
                    .attr('opacity', 0)
                    .attr('fill', '#296FFF')
                    .attr('stroke', '#296FFF')

                mapOverlays.exit().remove()
            }
            chart.renderTop = function () {
                mapTop = chart.body().append('g').attr('class', 'map-top')
                chart.mapArea()
                chart.mapInterior()
                chart.mapOutline()
                chart.mapOverlays()
            }
            /* ----------------------------渲染省市中心点------------------------  */
            chart.renderCenter = function () {
                // let latlng = handleData[0].properties.center
                // let position = projection(me.scale)(latlng)
                // d3.select('.yan-pan-modal').attr(
                //     'style',
                //     `left:${position[0] + 90}px;top:${position[1] - 20}px;display:block`,
                // )
            }

            /* ----------------------------渲染图标题------------------------  */
            chart.renderTitle = function () {
                chart
                    .svg()
                    .append('text')
                    .classed('title', true)
                    .attr('x', chart.width() / 2)
                    .attr('y', 0)
                    .attr('dy', '2em')
                    .text(config.title)
                    .attr('fill', config.textColor)
                    .attr('text-anchor', 'middle')
                    .attr('stroke', config.textColor)
            }

            /* ----------------------------绑定鼠标交互事件------------------------  */
            chart.addMouseOn = function () {
                d3.selectAll('.mapOverlays')
                    .on('mouseover', function (d) {
                        const position = d3.mouse(chart.svg().node())
                        chart
                            .svg()
                            .append('text')
                            .classed('tip white', true)
                            .attr('x', position[0] + 5)
                            .attr('y', position[1])
                            .text(d.properties.name)
                            .attr('fill', 'white')
                            .classed('f16', true)
                            .classed('fb', true)

                        d3.select('.mapOverlays-' + d.properties.name).attr('opacity', 1)
                    })
                    .on('mouseleave', function (d) {
                        d3.select('.tip').remove()
                        d3.select('.mapOverlays-' + d.properties.name).attr('opacity', 0)
                    })
                    .on('mousemove', function () {
                        const position = d3.mouse(chart.svg().node())
                        d3.select('.tip')
                            .attr('x', position[0] + 5)
                            .attr('y', position[1] - 5)
                            .attr('fill', 'white')
                            .classed('f16', true)
                            .classed('fb', true)
                    })
                // .on('click', function (d) {
                //     d3.select('.yan-pan-modal').attr('style', `display:none`)
                //     const { level, adcode, parent } = d?.properties
                //     me.level = level
                //     me.adcode = adcode
                //     me.parentAdcode = parent.adcode
                //     if (level == 'city' || level === 'district') {
                //         me.getGeoDataFn()
                //     }
                // })
                // d3.selectAll('.map-icon')
                //     // .on('mouseover', function (d, i) {
                //     //     d3.select('.mapOverlays-' + d.properties.name).attr('opacity', 1)
                //     // })
                //     // .on('mouseleave', function (d, i) {
                //     //     d3.select('.mapOverlays-' + d.properties.name).attr('opacity', 0)
                //     // })
                //     .on('click', function (d, i) {
                //         me.currentMarker = d
                //         let position = projection(me.scale)([d.longitude, d.latitude])
                //         d3.selectAll('.map-icon').classed('white', false)
                //         d3.select('.map-icon-' + i).classed('white', true)
                //         d3.select('.yan-pan-modal').attr(
                //             'style',
                //             `left:${position[0] + 90}px;top:${position[1] - 20}px;display:block`,
                //         )
                //     })
            }

            chart.render = function () {
                // chart.renderTitle()

                chart.renderTop()

                chart.renderCenter()

                // chart.addMouseOn()
            }

            chart.renderChart()
        },
    },
}
</script>
<style lang="scss" scoped>
.map-icon {
    color: #296fff;

    &:hover {
        color: white;
    }
}

.yan-pan-modal {
    position: absolute;
    left: 0;
    top: 0;
    width: 130px;
    height: 73px;
    display: none;
    background: url('../../../assets/img/png/map-marker.png') no-repeat center / contain;
}

.dot {
    width: 8px;
    height: 8px;
    background: white;
    border-radius: 8px;
}
</style>
